/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package libs;

import java.io.*;
import java.text.DecimalFormat;
import java.util.Vector;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import org.ujmp.core.Matrix;
import org.ujmp.core.MatrixFactory;
import types.TDataSet;

/**
 *
 * @author musa-atas
 */
public class Utils {

    public static TDataSet loadDataSet(String title) {
        TDataSet ds = new TDataSet();
        JFileChooser chooser = new JFileChooser();
        chooser.setCurrentDirectory(new java.io.File("E:\\DataSet_yeni\\DS"));
        if (title.isEmpty()) {
            chooser.setDialogTitle("select Data Set file");
        } else {
            chooser.setDialogTitle(title);
        }
        chooser.setSize(new java.awt.Dimension(45, 37)); // Generated
        if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            ds = Utils.readDataSet(file.getAbsolutePath());
            return ds;
        }
        return null;
    }

    public static TDataSet readDataSet(String absolutePath) {
        TDataSet ds = new TDataSet();
        File file = new File(absolutePath);
        ds.path = file.getAbsolutePath();
        ds.fileName = file.getName();
        try {
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            DataInputStream dis = null;
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            dis = new DataInputStream(bis);
            String ret = "";
            ret = dis.readLine();

            if (ret.equals("class labels")) {
                ds.featureLabels = dis.readLine();
                ret = dis.readLine();
                if (ret.equals("number of repetition")) {
                    ret = dis.readLine();
                    ds.nRpt = Integer.parseInt(ret);
                    ret = dis.readLine();
                } else {
                    Utils.showMessage("Wrong Dataset Format:number of repetition was not exist in the current file");
                    return null;
                }
            } //eger text in icinde class labeller yoksa
            else {
                Utils.showMessage("Wrong Dataset Format:class labels were not exist in the current file");
                return null;
            }
            int n = 0;
            int nF = ds.featureLabels.split(";").length;
            Vector<Integer> cls = new Vector<Integer>();
            while (dis.available() != 0) {
                ret = dis.readLine();
                String[] str = ret.split(";");
                n = str.length;
                if (n < nF) {
                    continue;
                }
                cls.add(Integer.parseInt(str[str.length - 1]));
                ds.data.add(ret);
            }
            int max = Utils.getMax(cls);
            ds.nClasses = Integer.toBinaryString(max).length();
            ds.nFeatures = ret.split(";").length - 1;
            ds.featureIndexes = Utils.toString(Utils.getVector(0, ds.nFeatures - 1));
            fis.close();
            bis.close();
            dis.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ds;
    }

    public static Vector<String> readDataSetFile() {
        Vector<String> data = new Vector();
        JFileChooser chooser = new JFileChooser();
        chooser.setCurrentDirectory(new java.io.File("E:\\DataSet_yeni\\DS"));
        chooser.setDialogTitle("select Data Set file");
        chooser.setSize(new java.awt.Dimension(45, 37)); // Generated
        if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            try {
                FileInputStream fis = null;
                BufferedInputStream bis = null;
                DataInputStream dis = null;
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                dis = new DataInputStream(bis);

                String ret = "";
                while (dis.available() != 0) {
                    ret = dis.readLine();
                    data.add(ret);
                }
                fis.close();
                bis.close();
                dis.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return data;
    }

    public static int[] getVector(int a, int b) {
        int[] ret = new int[b - a + 1];
        for (int i = 0; i < ret.length; i++) {
            ret[i] = a + i;
        }
        return ret;
    }

    public static String toString(int[] v) {
        String ret = "";
        for (int i = 0; i < v.length; i++) {
            ret += v[i] + ";";
        }
        return ret;
    }

    public static void showMessage(String str) {
        JOptionPane.showMessageDialog(null, str);
    }

    public static void clearTable(JTable table) {
        while (table.getRowCount() > 0) {
            ((DefaultTableModel) table.getModel()).removeRow(0);
        }
    }

    public static TableModel getTableModel(Vector<String> v, String labels) {
        String[] classLabels = labels.split(";");
        if (v == null || v.size() == 0) {
            return null;
        }
        try {
            String[][] d = Utils.vectorToFullStringArray(v);
            int colNumber = v.get(0).split(";").length;
            String columnNames[] = new String[colNumber];
            for (int i = 0; i < classLabels.length; i++) {
                //columnNames[i] = i + "";
                columnNames[i] = classLabels[i];
            }
            columnNames[colNumber - 1] = "Class Label";

            Object data[][] = d;
            TableModel model = new DefaultTableModel(data, columnNames) {
            };
            return model;

        } catch (Exception e) {
            // TODO: handle exception
            return null;
        }
    }

    public static String[][] vectorToFullStringArray(Vector<String> v) {
        String[][] ret = new String[v.size()][v.get(0).split(";").length];
        for (int i = 0; i < v.size(); i++) {
            String[] str = v.get(i).split(";");
            for (int j = 0; j < str.length; j++) {
                ret[i][j] = str[j];
            }
        }
        return ret;
    }

    public static Vector<String> cloneVector(Vector<String> orgVector) {
        if (orgVector == null) {
            return null;
        }
        Vector<String> ret = new Vector<String>();
        for (int i = 0; i < orgVector.size(); i++) {
            ret.add(orgVector.get(i));
        }
        return ret;
    }

    public static Vector<String> getArtificialDataSet(int cols, int rows, String type) {
        Vector<String> ret = new Vector<String>();
        String str = "";
        MersenneTwister a = new MersenneTwister();
        for (int i = 0; i < rows; i++) {
            str = (i < (rows / 2)) ? "0;" : "1;";
            MersenneTwister ms = new MersenneTwister(a.nextLong());
            for (int j = 0; j < cols; j++) {
                double f = 0;
                if (type.equals("uniform")) {
                    f = formatDouble(ms.nextDouble() - 0.5);
                } else {
                    f = formatDouble(ms.nextGaussian());
                }
                str = f + ";" + str;
            }
            ret.add(str);
        }
        return ret;
    }

    public static float formatFloat(float num) {
        float q = 0f;
        try {
            DecimalFormat df = new DecimalFormat("#.###");
            q = Float.parseFloat(df.format(num).replace(",", "."));

        } catch (Exception e) {
            e.printStackTrace();
        }
        return q;
    }

    public static double formatDouble(double num) {
        double q = 0;
        try {
            DecimalFormat df = new DecimalFormat("#.###");
            q = Double.parseDouble(df.format(num).replace(",", "."));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return q;
    }

    public static void saveDataSet(Vector<String> v) {
        if (v == null || v.firstElement().split(";").length == 0) {
            return;
        }
        JFileChooser chooser = new JFileChooser();
        chooser.setCurrentDirectory(new java.io.File("E:\\DataSet_yeni\\DS"));
        chooser.setDialogTitle("save Data Set file as");
        chooser.setSize(new java.awt.Dimension(45, 37)); // Generated
        String labels = generateSequentialNumbers(v.firstElement().split(";").length);
        if (chooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            String fName = file.getAbsolutePath();
            String ek = "class labels\n";
            ek += labels + "\n";
            ek += "number of repetition\n" + 1 + "\n";
            ek += "training set";
            writeOverToFileAppend(fName, ek);
            for (String row : v) {
                writeOverToFileAppend(fName, row);
            }
        }
    }

    private static String generateSequentialNumbers(int n) {
        String ret = "";
        for (int i = 0; i < n; i++) {
            ret += i + ";";
        }
        return ret;
    }

    public static void writeOverToFileAppend(String file_name, String row) {
        File outFile = new File(file_name);
        FileWriter out;
        try {
            out = new FileWriter(outFile, true);//append
            out.write(row + "\n");
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void writeOverToFileNew(String file_name, String row) {
        File outFile = new File(file_name);
        FileWriter out;
        try {
            out = new FileWriter(outFile, false);//new
            out.write(row + "\n");
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void writeToFile(String file_name, String row) {
        File outFile = new File(file_name);
        FileWriter out;
        if (outFile.exists()) {
            showMessage(file_name + " isminde bir dosya zaten var islem devam edemez guvenlik nedeniyle dosyayi silip devam etmeniz gerekiyor");
            return;
        }
        try {
            out = new FileWriter(outFile, true);
            out.write(row);
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void plotMatrix(Vector<String> v) {
        double[][] d = vector2doubleArray(v);
        Matrix m = MatrixFactory.zeros(d.length, d[0].length);
        for (int i = 0; i < d.length; i++) {
            for (int j = 0; j < d[0].length; j++) {
                m.setAsDouble(d[i][j], i, j);
            }
        }
        m.showGUI();
    }

    public static double[][] vector2doubleArray(Vector<String> v) {
        double[][] ret = new double[v.size()][v.get(0).split(";").length - 1];
        for (int i = 0; i < v.size(); i++) {
            String[] str = v.get(i).split(";");
            int n = str.length - 1;
            for (int j = 0; j < n; j++) {
                ret[i][j] = Double.parseDouble(str[j]);
            }
        }
        return ret;
    }

    public static Vector<String> normalizeData(Vector<String> v, String type) {
        //assuming that class labels are positioned at the last column by default
        if (v == null || v.isEmpty()) {
            return null;
        }
        Normalization norm = new Normalization();
        String[][] nData = Utils.vectorToFullStringArray(v);
        String[][] rawData = Utils.getRawDataMatrix(nData);
        String[][] classLabels = Utils.getClassLabels(nData);
        //z-score normalization
        if (type.equals("zscore")) {
            rawData = norm.normalizeDataSetZScore(rawData);
        }
        //Min-Max Normalization
        if (type.equals("minmax")) {
            rawData = norm.normalizeDataSetMinMax(rawData);
        }
        //Unit Vector Normalization
        if (type.equals("unitvector")) {
            rawData = norm.normalizeDataSetUnitVector(rawData);
        }
        //Hyperbolic Tangent Normalization
        if (type.equals("tanh")) {
            rawData = norm.normalizeDataSetTanH(rawData);
        }
        //Sigmoidal Normalization
        if (type.equals("sigmoidal")) {
            rawData = norm.normalizeDataSetSigmoidal(rawData);
        }
        nData = Utils.mergeMatrices(rawData, classLabels);
        Vector<String> ret = Utils.ConvertStringArrayToVector(nData);
        return ret;
    }

    public static double getMean(int[][] data) {
        double toplam = 0;
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[0].length; j++) {
                toplam += data[i][j];
            }
        }
        return formatDouble(toplam / (data.length * data[0].length));
    }

    private static Vector<String> ConvertStringArrayToVector(String[][] d) {
        Vector<String> ret = new Vector<String>();
        String s = "";
        for (int i = 0; i < d.length; i++) {
            String[] q = d[i];
            for (int j = 0; j < q.length; j++) {
                s += q[j] + ";";
            }
            ret.add(s);
            s = "";
        }
        return ret;
    }

    public static double getMin(String[] obj) {
        double min = Double.parseDouble(obj[0]);
        for (int i = 0; i < obj.length; i++) {
            if (Double.parseDouble(obj[i]) < min) {
                min = Double.parseDouble(obj[i]);
            }
        }
        return min;
    }

    public static double getMax(String[] obj) {
        double max = Double.parseDouble(obj[0]);
        for (int i = 0; i < obj.length; i++) {
            if (Double.parseDouble(obj[i]) > max) {
                max = Double.parseDouble(obj[i]);
            }
        }
        return max;
    }

    public static String readPlainTextFromFile(String fileStr) {
        String ret = "";
        File file = new File(fileStr);
        try {
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            DataInputStream dis = null;
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            dis = new DataInputStream(bis);

            while (dis.available() != 0) {
                ret += dis.readLine() + "\n";
            }
            fis.close();
            bis.close();
            dis.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            return null;
        }
        return ret;
    }

    public static Vector<String> getAdaptiveTresholdValue(Vector<String> v, double a, double b) {
        Vector<String> ret = new Vector<String>();
        ret.add(v.get(0));
        ret.add(v.get(1));
        ret.add(v.get(2));
        for (int i = 4; i < v.size(); i += 2) {
            double n = Double.parseDouble(v.get(i));
            if (n > a && n <= b) {
                ret.add(v.get(i - 1));
                ret.add(v.get(i));
            }
        }
        return ret;
    }

    public static Vector<String> readDataFromFile(String fileStr) {
        Vector<String> ret = new Vector<String>();
        File file = new File(fileStr);
        try {
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            DataInputStream dis = null;
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            dis = new DataInputStream(bis);

            while (dis.available() != 0) {
                ret.add(dis.readLine());
            }
            fis.close();
            bis.close();
            dis.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            return null;
        }
        return ret;
    }

    public static String[][] ConvertArrayF2S(float[][] in) {
        String[][] ret = new String[in.length][in[0].length];
        for (int i = 0; i < ret.length; i++) {
            for (int j = 0; j < ret[0].length; j++) {
                ret[i][j] = in[i][j] + "";
            }
        }
        return ret;
    }

    public static float[][] ConvertArrayS2F(String[][] in) {
        float[][] ret = new float[in.length][in[0].length];
        for (int i = 0; i < ret.length; i++) {
            for (int j = 0; j < ret[0].length; j++) {
                ret[i][j] = Float.parseFloat(in[i][j]);
            }
        }
        return ret;
    }

    public static String[][] ConvertArrayD2S(double[][] in) {
        String[][] ret = new String[in.length][in[0].length];
        for (int i = 0; i < ret.length; i++) {
            for (int j = 0; j < ret[0].length; j++) {
                ret[i][j] = in[i][j] + "";
            }
        }
        return ret;
    }

    public static double[][] ConvertArrayS2D(String[][] in) {
        double[][] ret = new double[in.length][in[0].length];
        for (int i = 0; i < ret.length; i++) {
            for (int j = 0; j < ret[0].length; j++) {
                ret[i][j] = Double.parseDouble(in[i][j]);
            }
        }
        return ret;
    }

    public static double[] ConvertArrayS2D(String[] in) {
        double[] ret = new double[in.length];
        for (int i = 0; i < ret.length; i++) {
            ret[i] = Double.parseDouble(in[i]);
        }
        return ret;
    }

    public static String[][] ConvertArrayI2S(int[][] in) {
        String[][] ret = new String[in.length][in[0].length];
        for (int i = 0; i < ret.length; i++) {
            for (int j = 0; j < ret[0].length; j++) {
                ret[i][j] = in[i][j] + "";
            }
        }
        return ret;
    }

    public static int[][] ConvertArrayS2I(String[][] in) {
        int[][] ret = new int[in.length][in[0].length];
        for (int i = 0; i < ret.length; i++) {
            for (int j = 0; j < ret[0].length; j++) {
                ret[i][j] = Integer.parseInt(in[i][j]);
            }
        }
        return ret;
    }

    public static int[] ConvertArrayS2I(String[] in) {
        int[] ret = new int[in.length];
        for (int i = 0; i < ret.length; i++) {
            ret[i] = Integer.parseInt(in[i]);
        }
        return ret;
    }

    public static float[] cloneArray(float[] trInput) {
        float[] ret = new float[trInput.length];
        for (int i = 0; i < ret.length; i++) {
            ret[i] = trInput[i];
        }
        return ret;
    }

    public static int getInt(String param) {
        return Integer.parseInt(param);
    }

    public static float getFloat(String param) {
        return Float.parseFloat(param);
    }

    public static double getDouble(String param) {
        try {
            return Double.parseDouble(param);
        } catch (Exception e) {
            return 0;
        }
    }

    public static Vector cloneWeights(Vector v) {
        //dikkatli kullan cunku deep clone yapmiyor
        float[][] wInput = (float[][]) v.get(0);
        float[][] wOutput = (float[][]) v.get(1);
        float[][] tInput = clone(wInput);
        float[][] tOutput = clone(wOutput);

        Vector ret = new Vector();
        ret.add(tInput);
        ret.add(tOutput);
        return ret;
    }

    private static float[][] clone(float[][] p) {
        float[][] f = new float[p.length][p[0].length];
        for (int i = 0; i < f.length; i++) {
            for (int j = 0; j < f[0].length; j++) {
                f[i][j] = p[i][j];
            }
        }
        return f;
    }

    public static Vector cloneBias(Vector v) {
        //dikkatli kullan cunku deep clone yapmiyor
        float[] wInput = (float[]) v.get(0);
        float[] wOutput = (float[]) v.get(1);
        float[] tInput = clone(wInput);
        float[] tOutput = clone(wOutput);

        Vector ret = new Vector();
        ret.add(tInput);
        ret.add(tOutput);
        return ret;
    }

    private static float[] clone(float[] p) {
        float[] f = new float[p.length];
        for (int i = 0; i < f.length; i++) {
            f[i] = p[i];
        }
        return f;
    }

    public static String[][] loadDataSetForTest(Vector v1, boolean isPepper, boolean isPrediction, int outputSize) {
        if (v1.size() > 0) {
            String row = v1.get(0).toString();
            String[] dizi = row.split(";");
            String[][] data = null;
            int outS = outputSize;
            if (isPepper) {
                if (outS > 1) {
                    data = new String[v1.size()][dizi.length];
                } else {
                    data = new String[v1.size()][dizi.length - 1];
                }
            } else {
                //ikiden fazla class varsa binary donusumu yapilir
                if (outS > 1) {
                    data = new String[v1.size()][dizi.length - 1 + outputSize];
                } else {
                    //iki class ise output tek node kabul edilir, 0 veya 1 e uzakligina gore karar verilir
                    data = new String[v1.size()][dizi.length];
                }
                //data = new String[v1.size()][dizi.length + 1];
            }

            for (int i = 0; i < data.length; i++) {
                dizi = v1.get(i).toString().split(";");
                int j;
                if (isPepper) {
                    if (outS > 1) {
                        for (j = 0; j < data[0].length - 3; j++) {
                            data[i][j] = (dizi[j]);
                        }
                        if (Double.parseDouble(dizi[j]) < 5.0) {
                            data[i][j] = "0";
                            data[i][j + 1] = "0";
                        } else if (Double.parseDouble(dizi[j]) >= 5.0
                                && Double.parseDouble(dizi[j]) < 15.0) {
                            data[i][j] = "0";
                            data[i][j + 1] = "1";

                        } else {
                            data[i][j] = "1";
                            data[i][j + 1] = "1";

                        }
                        data[i][j + 2] = dizi[j + 2];
                    } else {
                        for (j = 0; j < data[0].length - 2; j++) {
                            data[i][j] = (dizi[j]);
                        }
                        if (isPrediction) {
                            data[i][j] = dizi[j];
                            data[i][j + 1] = dizi[j + 2];
                        } else {
                            data[i][j] = dizi[j + 1];
                            data[i][j + 1] = dizi[j + 2];
                        }
                    }
                } else {
//                    for (j = 0; j < data[0].length - 1; j++) {
//                        data[i][j] = (dizi[j]);
//                    }
//                    data[i][j] = dizi[j - 1];
                    if (outS > 1) {
                        for (j = 0; j < data[0].length - outS; j++) {
                            data[i][j] = (dizi[j]);
                        }
                        int n = Integer.parseInt(dizi[data[0].length - outS]);
                        String[] ek = Utils.getBinaryCode(n, outS);
                        int k = 0;
                        for (j = data[0].length - outS; j < data[0].length; j++) {
                            data[i][j] = ek[k++];
                        }
                    } else {
                        for (j = 0; j < data[0].length; j++) {
                            data[i][j] = (dizi[j]);
                        }
                    }

                }
            }
            return data;
        } else {
            return null;
        }
    }

    public static String[][] loadDataSet(Vector<String> v, boolean isPepper, boolean isPrediction, int outputSize) {
        Vector<String> v1 = new Vector<String>();
        v1 = Utils.cloneVector(v);
        int outS = outputSize;
        if (v1.size() > 0) {
            String row = v1.get(0).toString();
            String[] dizi = row.split(";");
            String[][] data = null;
            if (isPepper) {
                if (outS > 1) {
                    data = new String[v1.size()][dizi.length - 1];
                } else {
                    data = new String[v1.size()][dizi.length - 2];
                }

            } else {
                //ikiden fazla class varsa binary donusumu yapilir
                if (outS > 1) {
                    data = new String[v1.size()][dizi.length - 1 + outputSize];
                } else {
                    //iki class ise output tek node kabul edilir, 0 veya 1 e uzakligina gore karar verilir
                    data = new String[v1.size()][dizi.length];
                }
            }
            for (int i = 0; i < data.length; i++) {
                dizi = v1.get(i).toString().split(";");
                int j;
                if (isPepper) {
                    if (outS > 1) {
                        for (j = 0; j < data[0].length - 2; j++) {
                            data[i][j] = (dizi[j]);
                        }
                        if (Double.parseDouble(dizi[j]) < 5.0) {
                            data[i][j] = "0";
                            data[i][j + 1] = "0";
                        } else if (Double.parseDouble(dizi[j]) >= 5.0
                                && Double.parseDouble(dizi[j]) < 15.0) {
                            data[i][j] = "0";
                            data[i][j + 1] = "1";
                        } else {
                            data[i][j] = "1";
                            data[i][j + 1] = "1";
                        }
                    } else {
                        for (j = 0; j < data[0].length - 1; j++) {
                            data[i][j] = (dizi[j]);
                        }
                        // class labels are discrete or continous
                        // in the case of continous, classifier may predict the
                        // result
                        if (isPrediction) {
                            data[i][j] = dizi[j];
                        } else {
                            data[i][j] = dizi[j + 1];
                        }

                    }
                } else {
                    if (outS > 1) {
                        for (j = 0; j < data[0].length - outS; j++) {
                            data[i][j] = (dizi[j]);
                        }
                        int n = Integer.parseInt(dizi[data[0].length - outS]);
                        String[] ek = Utils.getBinaryCode(n, outS);
                        int k = 0;
                        for (j = data[0].length - outS; j < data[0].length; j++) {
                            data[i][j] = ek[k++];
                        }

                    } else {
                        for (j = 0; j < data[0].length; j++) {
                            data[i][j] = (dizi[j]);
                        }
                    }
                }
            }
            return data;
        } else {
            return null;
        }
    }

    public static String getRankedFeatureLabels(String classLabelString, String rankedB) {
        String ret = "";
        if (classLabelString == null || classLabelString.isEmpty() || rankedB.isEmpty()) {
            return ret;
        }
        String[] str = classLabelString.split(";");
        String[] rnk = rankedB.split(";");
        for (int i = 0; i < rnk.length; i++) {
            ret += str[Integer.parseInt(rnk[i])] + ";";
        }
        return ret;
    }

    public static String getVectorAsString(int i, int nCols) {
        String ret = "";
        for (int j = i; j <= nCols; j++) {
            ret += j + ";";
        }
        return ret;
    }

    private static String[][] getRawDataMatrix(String[][] d) {
        String[][] ret = new String[d.length][d[0].length - 1];
        for (int i = 0; i < d.length; i++) {
            for (int j = 0; j < d[0].length - 1; j++) {
                ret[i][j] = d[i][j];
            }
        }
        return ret;
    }

    private static String[][] getClassLabels(String[][] d) {
        String[][] ret = new String[d.length][1];
        for (int i = 0; i < d.length; i++) {
            for (int j = 0; j < 1; j++) {
                ret[i][j] = d[i][d[0].length - 1];
            }
        }
        return ret;
    }

    private static String[][] mergeMatrices(String[][] d, String[][] c) {
        String[][] ret = new String[d.length][d[0].length + 1];
        for (int i = 0; i < d.length; i++) {
            for (int j = 0; j < d[0].length; j++) {
                ret[i][j] = d[i][j];
            }
            ret[i][d[0].length] = c[i][0];
        }
        return ret;
    }

    public static Vector<String> getMatrixByFeatureIndexes(Vector<String> ds, String fx) {
        String[][] sa = Utils.vectorToFullStringArray(ds);
        if (sa[0].length <= fx.split(";").length) {
            return null;
        }
        int[] d = Utils.getVector(fx);
        String[][] sar = Utils.getMatrixSubsetByColumnIndexes(sa, d);
        Vector<String> ret = Utils.ConvertStringArrayToVector(sar);
        return ret;
    }

    public static long[][] transposeMatrix(long[][] p) {
        long[][] ret = new long[p[0].length][p.length];
        for (int i = 0; i < p.length; i++) {
            for (int j = 0; j < p[0].length; j++) {
                ret[j][i] = p[i][j];
            }
        }
        return ret;
    }

    public static double[][] transposeMatrix(double[][] p) {
        double[][] ret = new double[p[0].length][p.length];
        for (int i = 0; i < p.length; i++) {
            for (int j = 0; j < p[0].length; j++) {
                ret[j][i] = p[i][j];
            }
        }
        return ret;
    }

    public static String[][] transposeMatrix(String[][] p) {
        String[][] ret = new String[p[0].length][p.length];
        for (int i = 0; i < p.length; i++) {
            for (int j = 0; j < p[0].length; j++) {
                ret[j][i] = p[i][j];
            }
        }
        return ret;
    }

    private static int[] getVector(String fx) {
        String[] str = fx.split(";");
        int[] ret = new int[fx.split(";").length];
        for (int i = 0; i < ret.length; i++) {
            ret[i] = Integer.parseInt(str[i]);
        }
        return ret;
    }

    private static String[][] getMatrixSubsetByColumnIndexes(String[][] sa, int[] d) {
        String[][] sat = Utils.transposeMatrix(sa);
        String[] cl = sat[sat.length - 1];
        String[][] ret = new String[d.length + 1][sat[0].length];
        for (int i = 0; i < ret.length - 1; i++) {
            for (int j = 0; j < ret[0].length; j++) {
                ret[i][j] = sat[d[i]][j];
            }
        }
        ret[ret.length - 1] = cl;
        ret = Utils.transposeMatrix(ret);
        return ret;
    }

    public static void splitKFoldCV(String classLabels, Vector<String> data, int nRpt) {
        String dirName = JOptionPane.showInputDialog("write folder name:");
        Vector<String> indexes = Utils.readDataSetFile();
        for (int i = 0; i < indexes.size(); i++) {
            generateTrainAndTestSet(dirName, classLabels, i, data, indexes.get(i), nRpt);
        }

    }

    public static void splitKFoldCV(String classLabels, Vector<String> data, int nRpt, int nKFold) {
        String dirName = JOptionPane.showInputDialog("write folder name:");
        Vector<String> indexes = Utils.generateRandomIndexes(data.size(), nKFold);
        for (int i = 0; i < indexes.size(); i++) {
            generateTrainAndTestSet(dirName, classLabels, i, data, indexes.get(i), nRpt);
        }
    }

    private static Vector<String> generateRandomIndexes(int size, int nKFold) {
        int foldSize = size / nKFold;
        Vector<String> ret = new Vector<String>();
        Vector<Integer> indexArray = Utils.populateIndexArray(size);
        String str = "";
        for (int i = 0; i < nKFold; i++) {
            str = "";
            for (int j = 0; j < foldSize; j++) {
                int n = (int) (Math.random() * indexArray.size());
                str += indexArray.get(n) + ";";
                indexArray.remove(n);
            }
            ret.add(str);
            Utils.println(str);
        }

        return ret;
    }

    private static Vector<Integer> populateIndexArray(int size) {
        Vector<Integer> ret = new Vector<Integer>();
        for (int i = 0; i < size; i++) {
            ret.add(i);
        }
        return ret;
    }

    public static void repairTestFiles() {
        JFileChooser chooser = new JFileChooser();
        chooser.setCurrentDirectory(new java.io.File("E:\\DataSet_yeni\\DS\\BENCHMARK_DATASET\\PEPPER_KFOLD"));
        chooser.setDialogTitle("select test file");
        chooser.setSize(new java.awt.Dimension(45, 37)); // Generated
        if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            if (file.getName().equals("train.txt")) {
                showMessage("please select test.txt file");
                return;
            }
            String[] d = file.getAbsolutePath().split("\\\\");
            String dir = getFolderPath(d, 2);
            for (int ii = 1; ii < 6; ii++) {
                String fold = dir + "\\" + ii + ".FOLD\\test.txt";
                repairFile(fold);
            }
            showMessage("b.test.txt files were successfully repaired");
        }
    }

    private static String getFolderPath(String[] d, int n) {
        String path = "";
        for (int i = 0; i < d.length - n; i++) {
            path += d[i] + "\\";
        }
        return path;
    }

    private static void generateTrainAndTestSet(String dirName, String classLabels, int n, Vector<String> data, String testStr, int nRpt) {
        String strTest = "class labels\n" + classLabels + "\n" + "number of repetition\n" + nRpt + "\n" + "test set\n";
        String strTrain = "class labels\n" + classLabels + "\n" + "number of repetition\n" + nRpt + "\n" + "train set\n";

        Vector<String> train = Utils.cloneVector(data);
        String[] peppers = testStr.split(";");
        for (int j = 0; j < nRpt; j++) {
            for (int i = 0; i < peppers.length; i++) {
                String str = getRowData(train, peppers[i]);
                strTest += str + "\n";
            }
        }
        train = removeElements(train, peppers);
        for (int i = 0; i < train.size(); i++) {
            strTrain += train.get(i) + "\n";
        }
        String dir = "E:\\DataSet_yeni\\DS\\KFOLD";
        File file = new File(dir);
        file.mkdir();
        dir += "\\" + dirName;
        file = new File(dir);
        file.mkdir();
        dir += "\\" + (n + 1) + ".FOLD";
        String s = dir;
        file = new File(dir);
        file.mkdir();
        dir += "\\INCR_BTN";
        file = new File(dir);
        file.mkdir();
        dir += "\\RESULTS";
        file = new File(dir);
        file.mkdir();
        Utils.writeToFile(s + "\\test.txt", strTest);
        Utils.writeToFile(s + "\\train.txt", strTrain);
        Utils.repairFile(s + "\\test.txt");

        dir = "E:\\DataSet_yeni\\DS\\KFOLD\\" + dirName + "\\TEMPLATE";
        file = new File(dir);
        if (!file.exists()) {
            file.mkdir();
            s = dir;
            dir += "\\INCR_BTN";
            file = new File(dir);
            file.mkdir();
            dir += "\\RESULTS";
            file = new File(dir);
            file.mkdir();
            String dt = "class labels\n" + classLabels + "\nnumber of repetition\n" + nRpt + "\ntraining set\n";

            for (int i = 0; i < data.size(); i++) {
                dt += data.get(i) + "\n";
            }
            Utils.writeToFile(s + "\\all.txt", dt);
        }
    }

    private static void repairFile(String fold) {
        File file = new File(fold);

        try {
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            DataInputStream dis = null;
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            dis = new DataInputStream(bis);

            String data = "";
            data += dis.readLine() + "\n";
            data += dis.readLine() + "\n";
            data += dis.readLine() + "\n";
            data += dis.readLine() + "\n";
            data += dis.readLine() + "\n";

            Vector<String> org = new Vector<String>();
            while (dis.available() != 0) {
                org.add(dis.readLine());
            }
            String[] c1 = org.get(0).split(";");
            String[] c2 = org.get(1).split(";");
            String[] c3 = org.get(2).split(";");
            if (c1[c1.length - 1].equals(c2[c2.length - 1]) && c2[c2.length - 1].equals(c3[c3.length - 1])) {
                showMessage("no need to repair");
                fis.close();
                bis.close();
                dis.close();
                return;
            }

            Vector<String> ret = new Vector<String>();
            for (int i = 0; i < org.size() / 3; i++) {
                ret.add(org.get(i));
                ret.add(org.get(i + org.size() / 3));
                ret.add(org.get(i + 2 * org.size() / 3));
            }
            for (int i = 0; i < ret.size(); i++) {
                data += ret.get(i) + "\n";
            }
            writeOverToFileNew(file.getAbsolutePath(), data);
            fis.close();
            bis.close();
            dis.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            return;
        }
    }

    public static Vector<String> removeElements(Vector<String> train, String[] peppers) {
        Vector<String> ret = new Vector<String>();
        int[] d = ConvertArrayS2I(peppers);
        for (int i = 0; i < train.size(); i++) {
            if (!containsArray(i + 1, d)) {
                ret.add(train.get(i));
            }
        }
        return ret;
    }

    public static boolean containsArray(int i, int[] temp) {
        for (int j = 0; j < temp.length; j++) {
            if (i == temp[j]) {
                return true;
            }
        }
        return false;
    }

    private static String getRowData(Vector<String> temp, String aranan) {
        //sira index numarasina gore bul
        //int n = Integer.parseInt(aranan) - 1;
        int n = Integer.parseInt(aranan);
        String ret = temp.get(n);
        //temp.remove(n);
        return ret;
    }

    public static void print(double[][] ret) {
        for (int i = 0; i < ret.length; i++) {
            for (int j = 0; j < ret[0].length; j++) {
                System.out.print(ret[i][j] + "\t");
            }
            System.out.println();
        }
    }

    private static void println(String p) {
        System.out.println(p);
    }

    private static String[] getBinaryCode(int n, int size) {
        String[] ret = new String[size];
        for (int i = 0; i < ret.length; i++) {
            ret[i] = "0";
        }
        String str = Integer.toBinaryString(n);
        char[] c = str.toCharArray();
        for (int i = 0; i < c.length; i++) {
            ret[size - 1 - i] = "" + c[c.length - 1 - i];
        }
        return ret;
    }

    private static int getMax(Vector<Integer> p) {
        int max = p.firstElement();
        for (Integer n : p) {
            if (max < n) {
                max = n;
            }
        }
        return max;
    }
}
